package com.matt.service.impl;

import com.dotflat.cc.po.ChildrenImportPO;
import com.dotflat.cc.po.ChildrenPO;
import com.dotflat.cc.po.LeadsPO;
import com.dotflat.cc.po.ParentUserPO;
import com.dotflat.util.AssertUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.matt.commons.dto.sso.AreaDTO;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.commons.utils.MapConvertUtil;
import com.matt.commons.utils.RemoteCallUtil;
import com.matt.domain.*;
import com.matt.domain.course.ChildrenCourse;
import com.matt.domain.course.ChildrenCourseChangeRecord;
import com.matt.domain.mp.ParentUser;
import com.matt.domain.record.CheckRecord;
import com.matt.domain.rel.RelClassesChildren;
import com.matt.domain.rel.RelUserChildren;
import com.matt.domain.vo.ChildrenContractInfoRecordVo;
import com.matt.foundation.DO.*;
import com.matt.foundation.constant.*;
import com.matt.foundation.dto.crm.ProductDTO;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.query.ChildrenNurseryQuery;
import com.matt.foundation.query.ChildrenQuery;
import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.utils.JsonValidateUtil;
import com.matt.foundation.utils.annotation.OptsTrace;
import com.matt.foundation.vo.*;
import com.matt.foundation.vo.children.BabyNClassInfoVO;
import com.matt.foundation.vo.children.WebChildrenVo;
import com.matt.repository.*;
import com.matt.repository.base.*;
import com.matt.repository.course.ChildrenCourseChangeRecordRepository;
import com.matt.repository.course.ChildrenCourseRepository;
import com.matt.repository.record.CheckRecordRepository;
import com.matt.repository.record.ChildrenNurseryInfoRecordRepository;
import com.matt.repository.rel.RelClassesChildrenRepository;
import com.matt.repository.rel.RelUserChildrenRepository;
import com.matt.service.ChildrenService;
import com.matt.service.FeedsService;
import com.matt.service.UploadService;
import com.matt.service.WxPushService;
import com.matt.service.remoteCall.SsoCallService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.commons.model.ErrorCode.DATE_FORMAT_ERROR;
import static com.matt.foundation.model.ErrorCode.*;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2017/7/13
 * *******************************
 */
@Service
@Slf4j
public class ChildrenServiceImpl implements ChildrenService {

    @Autowired
    private ChildrenRepository childrenRepository;
    @Autowired
    private ChildrenCouponCardRepository childrenCouponCardRepository;

    @Autowired
    private UserChildrenRepository userChildrenRepository;

    @Autowired
    private CheckRecordRepository checkRecordRepository;

    @Autowired
    private ClassesChildrenRepository classesChildrenRepository;

    @Autowired
    private ChildrenCheckRecordRepository childrenCheckRecordRepository;

    @Autowired
    private ChildrenLiveRecordRepository childrenLiveRecordRepository;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private ChildrenExtendInfoRepository childrenExtendInfoRepository;

    @Autowired
    private ChildrenContractInfoRecordRepository childrenContractInfoRecordRepository;

    @Autowired
    private ChildChildrenExtendRepository childChildrenExtendRepository;

    @Autowired
    private FeedsService feedsService;

    @Autowired
    private ChildrenCourseChangeRecordRepository childrenCourseChangeRecordRepository;

    @Autowired
    private RelClassesChildrenRepository relClassesChildrenRepository;

    @Autowired
    private ClassesRepository classesRepository;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private ChildrenCourseRepository childrenCourseRepository;

    @Autowired
    private AppUserRepository appUserRepository;

    @Autowired
    private RelUserChildrenRepository relUserChildrenRepository;

    @Autowired
    private ChildrenNativeRepository childrenNativeRepository;

    @Autowired
    private ClassNativeRepository classNativeRepository;

    @Autowired
    private WxPushService wxPushService;

    @Autowired
    private BaseNativeSqlRepository baseNativeSqlRepository;

    @Autowired
    private ChildrenExtendInfoRepository extendInfoRepository;

    @Autowired
    private ChildrenNurseryInfoRecordRepository childrenNurseryInfoRecordRepository;

    @Autowired
    private WorkDateRepository workDateRepository;


    @Value("${spring.profiles.active}")
    private String env;

    @Value("${server.crm.url}")
    private String crmServerURL;


    @Override
    public Children update(StaffDTO staff, String childrenId, ChildrenPO children) {
        Children c = childrenRepository.findFirstByIdAndAreaId(childrenId, staff.getAreaId());
        if (c == null) {
            throw new BusinessException(CHILDREN_NOT_EXIST, "宝宝不存在");
        }

        if (children.getCouponCard()!=null){
            c.setUseTime(new Date());
            c.setCouponCard(children.getCouponCard());
            ChildrenCouponCard  couponCard= childrenCouponCardRepository.findByChildrenIdAndCouponCard(c.getId(),children.getCouponCard());
            if(couponCard!=null){
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "该优惠卷已使用");
            }
//            c.setUseTime(new Date());
            couponCard=new ChildrenCouponCard();
            couponCard.setChildrenId(c.getId());
            couponCard.setStatus(1);
            couponCard.setUseTime(new Date());
            couponCard.setUserName("园所端使用");
            childrenCouponCardRepository.save(couponCard);
        }
        CopyUtils.copyProperties(children, c);


        //先删除在添加
        relUserChildrenRepository.deleteByChildrenId(childrenId);

        for (int i = 0; i < children.getLinkMans().size(); i++) {
            ParentUserPO po = children.getLinkMans().get(i);

            ParentUser parentUser = appUserRepository.findByPhone(po.getPhone());
            if (Objects.isNull(parentUser)) {
                parentUser = ParentUser.of(po.getName(), po.getPhone(), po.getCompany(),po.getProvince(),po.getCity(),po.getDistrict(),po.getDetailedAddress(),po.getEducation(),po.getPosition(),po.getEmail());
                //创建相应联系人
                parentUser.setEmail(po.getEmail());
                parentUser = appUserRepository.save(parentUser);
            }

            relUserChildrenRepository.save(RelUserChildren.of(parentUser.getId(), c.getId(), po.getRelation(), po.getRemark()));
        }
        if (Objects.nonNull(children.getCameraValidTo())) {
            ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
            if (Objects.nonNull(extendInfo)) {
                if (children.getCameraValidTo() != null && !StringUtils.equals(children.getCameraValidTo(), "")) {
                    extendInfo.setCameraValidTo(DateUtil.parseToDateMilis(children.getCameraValidTo() + " 23/59/59"));
                    childrenExtendInfoRepository.save(extendInfo);
                }
            }
        }

        c = childrenRepository.save(c);

        return c;
    }

    @Override
    public Children addWithRealtion(String ticket, StaffDTO staff, ChildrenPO children) {
//新增逻辑
        LeadsPO param = new LeadsPO();
        param.setBirthday(children.getBirthday());
        //todo  顾问添加
        param.setChannel("老师添加");  //渠道
        param.setFromUser(String.format("%s(%s)", staff.getRealName(), staff.getMobile()));  //介绍人
        param.setFromUserId(staff.getId()); //介绍人id

        param.setChildName(children.getName());  //孩子姓名
        param.setGender(children.getGender()); //性别
        param.setBirthday(children.getBirthday());  //孩子生日
        param.setNickName(children.getNickName()); //孩子昵称
        param.setEnglishName("");


        param.setBloodType(children.getBloodType()); //血型
        param.setNationality(children.getNationality()); //国籍
        param.setTargetGarden(children.getTargetGarden()); //目标幼儿园
        param.setRegisterResidence(children.getRegisterResidence()); //户籍所在地
        param.setRegisterType(children.getRegisterType()); //户籍类型
        param.setLanguageEnvironment(children.getLanguageEnvironment());//所处语言环境

        ParentUserPO parent = children.getLinkMans().get(0);

        param.setName(parent.getName());  //家长姓名
        param.setRelationship(parent.getRelation()); //关系
        param.setMobile(parent.getPhone()); //联系电话
        param.setHomeAddress(parent.getProvince() + "" + parent.getCity() + "" + parent.getDistrict() + "" +parent.getDetailedAddress()); //家庭住址
        param.setCompany(parent.getCompany()); //工作单位
        param.setDuty(parent.getPosition()); //职务
        param.setDegree(parent.getEducation()); // 学历")

        param.setAreaId(staff.getAreaId());
        param.setStaffId(staff.getId());
        param.setStaffName(staff.getRealName());

        //最近跟进记录
        param.setLastFollowRecord(String.format("%s(%s)老师于 %s 手动添加",
                staff.getRealName(), staff.getMobile(), com.matt.commons.utils.DateUtil.toNormalString(new Date())));

        Map p = MapConvertUtil.obejctToMap(param);

        //patch for birthday/lastFollowTime
        if (children.getBirthday() != null) {
            p.put("birthday", com.matt.commons.utils.DateUtil.toNormalString(children.getBirthday()));
        }

        //先添加CRM客户
//        HashMap result = RemoteCallUtil.call(crmServerURL + "/api/other_system/create_clientele", p, ticket, HashMap.class, "创建客户失败");
//
//        String crmClienteleId = (String) result.get("id");

        //todo 注销，功能未知
//        Children c= childrenRepository.findByCrmClienteleId(crmClienteleId);
//        if(null != c){
//            throw new BusinessException(CHILDREN_NOT_EXIST,"宝贝/客户 已经存在");
//        }

        //创建教务i系统宝宝
        Children c = Children.of_now(children.getName(),
                Objects.isNull(children.getNickName()
                ) ? "" : children.getNickName(),
                children.getGender(),
                children.getBirthday(),
                staff.getAreaId(),
                Objects.isNull(children.getAddress()) ? "" : children.getAddress(),
                staff.getId());
        c.setCouponCard(children.getCouponCard());




        //最后如果有生效时间，则开始激活宝宝
        Date nursyValidDate = children.getNursyValidTo();
        if (nursyValidDate != null && nursyValidDate.compareTo(new Date()) > 0) {
            //指定日期有效
            c.setCourseStartDate(new Date());
            c.setStatus(ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());
        }
        c = add(c, parent.getPhone(), parent.getName(), parent.getCompany(), parent.getRelation(),parent.getProvince(),parent.getCity(),parent.getDistrict(),parent.getDetailedAddress(),parent.getEducation(),parent.getPosition(),parent.getEmail());
        if (children.getCouponCard()!=null){
            ChildrenCouponCard  couponCard= childrenCouponCardRepository.findByChildrenIdAndCouponCard(c.getId(),children.getCouponCard());
            if(couponCard!=null){
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "该优惠卷已使用");
            }
//            c.setUseTime(new Date());
            couponCard=new ChildrenCouponCard();
            couponCard.setChildrenId(c.getId());
            couponCard.setStatus(1);
            couponCard.setUserName("园所端使用");
            couponCard.setUseTime(new Date());
            childrenCouponCardRepository.save(couponCard);
        }
        //处理更多的家长
        for (int i = 1; i < children.getLinkMans().size(); i++) {
            ParentUserPO po = children.getLinkMans().get(i);

            ParentUser parentUser = appUserRepository.findByPhone(po.getPhone());
            if (Objects.isNull(parentUser)) {
                parentUser = ParentUser.of(po.getName(), po.getPhone(), po.getCompany(),po.getProvince(),po.getCity(),po.getDistrict(),po.getDetailedAddress(),po.getEducation(),po.getPosition(),po.getEmail());
                //创建相应联系人
                parentUser.setEmail(po.getEmail());
                parentUser = appUserRepository.save(parentUser);
            }

            relUserChildrenRepository.save(RelUserChildren.of(parentUser.getId(), c.getId(), po.getRelation(), po.getRemark()));
        }

        if (nursyValidDate != null && nursyValidDate.compareTo(new Date()) > 0 && children.getCameraValidTo() != null && !StringUtils.equals(children.getCameraValidTo(), "")) {
            //处理托班激活信息
            ChildrenExtendInfo extendInfo = extendInfoRepository.findByChildrenId(c.getId());
            //托班相关信息
            extendInfo.setNurseryEndDate(nursyValidDate);
            extendInfo.setNurseryStatus(ChildrenConstant.NurseryStatus.HAS_COURSE.codeOf());
            extendInfo.setCameraValidTo(DateUtil.parseToDateMilis(children.getCameraValidTo() + " 23/59/59"));
            extendInfoRepository.save(extendInfo);
        }

        return c;
    }



    @Override
    public Children addWithRealtion(String ticket, StaffDTO staff, ChildrenPO children,String areaId) {
         //新增逻辑
        LeadsPO param = new LeadsPO();
        param.setBirthday(children.getBirthday());
        param.setChannel("老师添加");  //渠道
        param.setFromUser(String.format("%s(%s)", staff.getRealName(), staff.getMobile()));  //介绍人
        param.setFromUserId(staff.getId()); //介绍人id

        param.setChildName(children.getName());  //孩子姓名
        param.setGender(children.getGender()); //性别
        param.setBirthday(children.getBirthday());  //孩子生日
        param.setNickName(children.getNickName()); //孩子昵称
        param.setEnglishName("");

        param.setBloodType(children.getBloodType()); //血型
        param.setNationality(children.getNationality()); //国籍
        param.setTargetGarden(children.getTargetGarden()); //目标幼儿园
        param.setRegisterResidence(children.getRegisterResidence()); //户籍所在地
        param.setRegisterType(children.getRegisterType()); //户籍类型
        param.setLanguageEnvironment(children.getLanguageEnvironment());//所处语言环境

        ParentUserPO parent = children.getLinkMans().get(0);

        param.setName(parent.getName());  //家长姓名
        param.setRelationship(parent.getRelation()); //关系
        param.setMobile(parent.getPhone()); //联系电话
        param.setHomeAddress(parent.getProvince() + "" + parent.getCity() + "" + parent.getDistrict() + "" +parent.getDetailedAddress()); //家庭住址
        param.setCompany(parent.getCompany()); //工作单位
        param.setDuty(parent.getPosition()); //职务
        param.setDegree(parent.getEducation()); // 学历")

        param.setAreaId(areaId);
        param.setStaffId(staff.getId());
        param.setStaffName(staff.getRealName());

        //最近跟进记录
        param.setLastFollowRecord(String.format("%s(%s)老师于 %s 手动添加",
                staff.getRealName(), staff.getMobile(), com.matt.commons.utils.DateUtil.toNormalString(new Date())));

        Map p = MapConvertUtil.obejctToMap(param);
        p.put("areaId",areaId);
        //patch for birthday/lastFollowTime
        if (children.getBirthday() != null) {
            p.put("birthday", com.matt.commons.utils.DateUtil.toNormalString(children.getBirthday()));
        }

//        //先添加CRM客户
//        HashMap result = RemoteCallUtil.call(crmServerURL + "/api/other_system/create_clienteleV2", p, ticket, HashMap.class, "创建客户失败");
//
//        String crmClienteleId = (String) result.get("id");

        //todo 注销功能
//        Children c= childrenRepository.findByCrmClienteleId(crmClienteleId);
//        if(null != c){
//            throw new BusinessException(CHILDREN_NOT_EXIST,"宝贝/客户 已经存在");
//        }


        //创建教务i系统宝宝
        Children c = Children.of(children.getName(),
                Objects.isNull(children.getNickName()) ? "" : children.getNickName(),
                children.getGender(),
                children.getBirthday(),
                areaId,
                Objects.isNull(children.getAddress()) ? "" : children.getAddress(),
                staff.getId(),
                staff.getId());

        //最后如果有生效时间，则开始激活宝宝
        Date nursyValidDate = children.getNursyValidTo();
        if (nursyValidDate != null && nursyValidDate.compareTo(new Date()) > 0) {
            //指定日期有效
            c.setCourseStartDate(new Date());
            c.setStatus(ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());
        }
        c = add(c, parent.getPhone(), parent.getName(), parent.getCompany(), parent.getRelation(),parent.getProvince(),parent.getCity(),parent.getDistrict(),parent.getDetailedAddress(),parent.getEducation(),parent.getPosition(),parent.getEmail());

        //处理更多的家长
        for (int i = 1; i < children.getLinkMans().size(); i++) {
            ParentUserPO po = children.getLinkMans().get(i);

            ParentUser parentUser = appUserRepository.findByPhone(po.getPhone());
            if (Objects.isNull(parentUser)) {
                parentUser = ParentUser.of(po.getName(), po.getPhone(), po.getCompany(),po.getProvince(),po.getCity(),po.getDistrict(),po.getDetailedAddress(),po.getEducation(),po.getPosition(),po.getPosition());
                //创建相应联系人
                parentUser.setEmail(po.getEmail());
                parentUser = appUserRepository.save(parentUser);
            }

            relUserChildrenRepository.save(RelUserChildren.of(parentUser.getId(), c.getId(), po.getRelation(), po.getRemark()));
        }

        if (nursyValidDate != null && nursyValidDate.compareTo(new Date()) > 0 && children.getCameraValidTo() != null && !StringUtils.equals(children.getCameraValidTo(), "")) {
            //处理托班激活信息
            ChildrenExtendInfo extendInfo = extendInfoRepository.findByChildrenId(c.getId());
            //托班相关信息
            extendInfo.setNurseryEndDate(nursyValidDate);
            extendInfo.setNurseryStatus(ChildrenConstant.NurseryStatus.HAS_COURSE.codeOf());
            extendInfo.setCameraValidTo(DateUtil.parseToDateMilis(children.getCameraValidTo() + " 23/59/59"));
            extendInfoRepository.save(extendInfo);
        }

        return c;
    }
    @Transactional
    @Override
    public Children add(Children children, String phone, String name, String company, String relation,String province,String city,String district,String detailedAddress,String education,String position,String email) {
//        AreaDTO area = ssoCallService.getAreaById(children.getAreaId());

//        Integer areaChildNum = childrenRepository.countByAreaIdAndCreatedBetween(children.getAreaId(), DateUtil.getBeginOfCurrentMonth(), DateUtil.getEndOfCurrentMonth());
//        String areaCode=area.getCode();
//        if(areaCode==null||"".equals(areaCode)){
//            ModelUtil.getRandomNumber(2);
//        }
//        String code = ModelUtil.getAreaCityCode(area.getName()) + area.getCode() + DateUtil.millisToDateTime(children.getCreated().getTime(), "yyyy") + DateUtil.millisToDateTime(children.getCreated().getTime(), "MM") + ModelUtil.numToStr(areaChildNum + 1) + children.getGender();
//        children.setCode(code);

        // int month = DateUtil.betweenMonths(new Date(), children.getBirthday());
        children.setStatus(ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());//新增直接默认孩子为激活状态
        childrenRepository.save(children);

        //添加一个宝宝的扩展信息
        ChildrenExtendInfo extendInfo = ChildrenExtendInfo.of(children.getId(), children.getName());
        childrenExtendInfoRepository.save(extendInfo);

        ChildrenCourse childrenCourse = ChildrenCourse.of(children.getId());
        childrenCourseRepository.save(childrenCourse);
        //早教相关

        ParentUser parentUser = appUserRepository.findByPhone(phone);
        if (Objects.isNull(parentUser))
            parentUser = ParentUser.of(name, phone, company,province,city,district,detailedAddress,education,position,email);
        else {
            parentUser.setCompany(company);
            parentUser.setName(name);
            parentUser.setProvince(province);
            parentUser.setCity(city);
            parentUser.setDistrict(district);
            parentUser.setDetailedAddress(detailedAddress);
            parentUser.setEducation(education);
            parentUser.setPosition(position);
            parentUser.setEmail(email);
        }

        //创建相应联系人
        parentUser = appUserRepository.save(parentUser);

        relUserChildrenRepository.save(RelUserChildren.of(parentUser.getId(), children.getId(), relation, ""));
        return children;
    }

    @Transactional
    @Override
    public Children add1(Children children, String phone, String name, String company, String relation, String province, String city, String district, String detailedAddress, String education, String position, String email, Date birthDay) {
//        AreaDTO area = ssoCallService.getAreaById(children.getAreaId());

//        Integer areaChildNum = childrenRepository.countByAreaIdAndCreatedBetween(children.getAreaId(), DateUtil.getBeginOfCurrentMonth(), DateUtil.getEndOfCurrentMonth());
//        String areaCode=area.getCode();
//        if(areaCode==null||"".equals(areaCode)){
//            ModelUtil.getRandomNumber(2);
//        }
//        String code = ModelUtil.getAreaCityCode(area.getName()) + area.getCode() + DateUtil.millisToDateTime(children.getCreated().getTime(), "yyyy") + DateUtil.millisToDateTime(children.getCreated().getTime(), "MM") + ModelUtil.numToStr(areaChildNum + 1) + children.getGender();
//        children.setCode(code);

        // int month = DateUtil.betweenMonths(new Date(), children.getBirthday());
        children.setStatus(ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());//新增直接默认孩子为激活状态
//        children.setStatus(5);//新增直接默认孩子待续费
        childrenRepository.save(children);

        //添加一个宝宝的扩展信息
        ChildrenExtendInfo extendInfo = ChildrenExtendInfo.of(children.getId(), children.getName());
        childrenExtendInfoRepository.save(extendInfo);

        ChildrenCourse childrenCourse = ChildrenCourse.of(children.getId());
        childrenCourseRepository.save(childrenCourse);
        //早教相关

        ParentUser parentUser = appUserRepository.findByPhone(phone);
        if (Objects.isNull(parentUser))
            parentUser = ParentUser.of1(name, phone, company,province,city,district,detailedAddress,education,position,email,birthDay);

        else {
            parentUser.setBirthDay(birthDay);
            parentUser.setCompany(company);
            parentUser.setName(name);
            parentUser.setProvince(province);
            parentUser.setCity(city);
            parentUser.setDistrict(district);
            parentUser.setDetailedAddress(detailedAddress);
            parentUser.setEducation(education);
            parentUser.setPosition(position);
            parentUser.setEmail(email);
        }

        //创建相应联系人
        parentUser = appUserRepository.save(parentUser);

        relUserChildrenRepository.save(RelUserChildren.of(parentUser.getId(), children.getId(), relation, ""));
        return children;
    }

    @Transactional
    @Override
    public Children edit(String areaId, String id, String name, String nickName, String birthday, int gender, String weight, String height, String header, String address, String remark) {
        Children children = childrenRepository.findByIdAndAreaId(id, areaId);
        if (children == null) {
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
        }
        children.setName(name);
        children.setNickName(nickName);
        children.setBirthday(com.matt.commons.utils.DateUtil.parseToDate(birthday));
        children.setGender(gender);
        children.setWeight(weight);
        children.setHeight(height);
        children.setHeader(header);
        children.setAddress(address);
        children.setRemark(remark);
        return childrenRepository.save(children);
    }

    @Transactional
    @Override
    public Children active(String clienteleId, String contractBeginDate, String contractEndDate, String productJson) {

        Children children = childrenRepository.findByCrmClienteleId(clienteleId);

        StaffDTO operator = ssoCallService.getStaffDTO(null, children.getStaffId());

        if (DateUtil.parseToDate(contractEndDate).compareTo(new Date()) > 0)
            children.setStatus(ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());

        Date beginDate = DateUtil.parseToDate(contractBeginDate);
        if (Objects.isNull(children.getCourseStartDate()) || children.getCourseStartDate().compareTo(beginDate) > 0)
            children.setCourseStartDate(beginDate);
        childrenRepository.save(children);

        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(children.getId());
        List<ProductDTO> list = JsonValidateUtil.readListFormJson(productJson, ProductDTO.class);
        for (ProductDTO product : list) {
            if (product.getType() == ContractConstant.Category.EARLY.codeOf()) {
                Integer times = Integer.valueOf(product.getCount());
                extendInfo.setEarlyLeftCourseNum(extendInfo.getEarlyLeftCourseNum() == -1 ? times : extendInfo.getEarlyLeftCourseNum() + times);
                extendInfo.setEarlyTotalCourseNum(extendInfo.getEarlyTotalCourseNum() == -1 ? times : extendInfo.getEarlyTotalCourseNum() + times);

                ChildrenCourseChangeRecord changeRecord = ChildrenCourseChangeRecord.of(operator.getId(), children.getId(), "新合同录入", times, extendInfo.getEarlyLeftCourseNum(), operator.getRealName());
                childrenCourseChangeRecordRepository.save(changeRecord);
            } else if (product.getType() == ContractConstant.Category.NURSERY.codeOf()) {
                Date nurseryEndDate = DateUtil.parseToDate(contractEndDate);
                //托班相关
                if (extendInfo.getNurseryEndDate().getTime() < nurseryEndDate.getTime()) {
                    extendInfo.setNurseryEndDate(nurseryEndDate);
                }
                extendInfo.setNurseryStatus(ChildrenConstant.NurseryStatus.HAS_COURSE.codeOf());
            } else if (product.getType() == ContractConstant.Category.CAMERA.codeOf()) {
                Integer count = Integer.valueOf(product.getCount());
                Date baseDate = extendInfo.getCameraValidTo();
                if (baseDate == null) {
                    baseDate = new Date();
                }

                Long validTo = DateUtil.plusMonths(baseDate.getTime(), count);
                Date validToDate = new Date(validTo);

                extendInfo.setCameraValidTo(validToDate);
            } else {
                return children;
            }

            childrenExtendInfoRepository.save(extendInfo);
        }
        return children;
    }

    @Override
    public Page<Children> findChildrenPage(ChildrenQuery childrenQuery) {
        Specification<Children> specification = new Specification<Children>() {
            @Override
            public Predicate toPredicate(Root<Children> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();

                if (StringUtils.isNotBlank(childrenQuery.getName()))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("name"), "%" + childrenQuery.getName() + "%")));

                if (StringUtils.isNotBlank(childrenQuery.getAreaId()))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("areaId"), childrenQuery.getAreaId())));

                if (StringUtils.isNotBlank(childrenQuery.getCode()))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("value"), "%" + childrenQuery.getCode() + "%")));

                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("isDisplayForAdmin"), false)));
                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(criteriaBuilder.desc(root.get("created")));
                return query.getRestriction();
            }
        };
        Pageable pageable = PageRequest.of(childrenQuery.getPageNum(), childrenQuery.getPageSize());
        Page<Children> page = childrenRepository.findAll(specification, pageable);
        return page;
    }

    public Page<Children> findTianBoChildrenPage(String areaId, PageRequest pageRequest){
        Specification<Children> specification = new Specification<Children>() {
            @Override
            public Predicate toPredicate(Root<Children> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();

                predicates.add(criteriaBuilder.equal(root.get("areaId"), areaId));

                predicates.add(criteriaBuilder.isNotNull(root.get("imgUrl")));
                predicates.add(criteriaBuilder.isFalse(root.get("deleted")));

                query.where(predicates.toArray(new Predicate[predicates.size()]));

                query.orderBy(criteriaBuilder.desc(root.get("created")));

                return query.getRestriction();
            }
        };

        Page<Children> page = childrenRepository.findAll(specification, pageRequest);

        return page;
    }

    @Override
    public List<ChildrenListVo> getChildrenByArea(String areaId, String name) {
        List<Children> children = Lists.newArrayList();
        if (org.apache.commons.lang.StringUtils.isBlank(name))
            children = childrenRepository.findByAreaIdAndDeleted(areaId, false);
        else
            children = childrenRepository.findByAreaIdAndNameLikeAndDeleted(areaId, name, false);
        List<ChildrenListVo> childrenList = children.stream().map(o -> ChildrenListVo.of(o)).collect(Collectors.toList());
        return childrenList;
    }

    @Transactional
    @Override
    public Boolean nurseryTransfer(String classesId, String childrenId, String staffId, String remark, String oldClassesId) {
        Classes classes = classesRepository.getOne(classesId);
        //Long nowNum = relClassesChildrenRepository.countByClassesId(classesId);
        Long nowNum = classNativeRepository.findCountByClassesId(classesId);
        if (classes.getLimitNum() <= nowNum) // nowNum+1
            throw new BusinessException(ErrorCode.CLASSES_STUDENT_LIMIT, "该班级已满员");

        Integer category = classes.getCategory();
        if (category != null) {
            if (StringUtils.isNotBlank(oldClassesId))
                relClassesChildrenRepository.deleteByChildrenIdAndAndClassesId(childrenId, oldClassesId);
            Children children = childrenRepository.getOne(childrenId);
            if (category == 1)
                children.setNurseryTransferReason(remark);
            if (category == 2)
                children.setEarlyTransferReason(remark);
            childrenRepository.save(children);

            RelClassesChildren rel = RelClassesChildren.of(childrenId, classesId);
            relClassesChildrenRepository.save(rel);
        }
        return true;
    }

    @Override
    public Page<ChildrenNurseryListDO> getNurseryValidChildren(ChildrenNurseryQuery query) {
        List<ChildrenNurseryListDO> childrenList = childChildrenExtendRepository.findChildByNurseryStatus(query);
        childrenList.forEach(o -> o.setMonth(DateUtil.betweenMonths(new Date(), o.getBirthday())));
        Long count = childChildrenExtendRepository.countChildByNurseryStatus(query);

        return new PageImpl<ChildrenNurseryListDO>(childrenList, PageRequest.of(query.getPageNum(), query.getPageSize()), count);
    }

    @Override
    public List<ChildrenListVo> getHasChildrenByArea(String areaId) {
        List<Children> children = childrenRepository.findByAreaIdAndStatus(areaId, ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());
        List<ChildrenListVo> childrenList = children.stream().map(o -> ChildrenListVo.of(o)).collect(Collectors.toList());
        return childrenList;
    }

    @Override
    public List<ChildrenListDO> getChildrenNonClassesNurseryValid(String areaId, Integer category) {
        List<ChildrenListDO> allChildren;
        if (category == ClassesConstant.Category.NURSERY.codeOf())
            allChildren = childChildrenExtendRepository.findChildrenByNurseryStatus(ChildrenConstant.NurseryStatus.HAS_COURSE.codeOf(), areaId);
        else
            allChildren = childChildrenExtendRepository.findChildrenByEarlyStatusActive(areaId);
        List<ChildrenListDO> existChildren = classesChildrenRepository.findChildrenByClassesTypeAndArea(category, areaId);
        List<ChildrenListDO> childrenList = allChildren.stream().filter(o -> isMatch(o, existChildren)).collect(Collectors.toList());
        return childrenList;
    }

    public boolean isMatch(ChildrenListDO vo, List<ChildrenListDO> objects) {
        return !objects.stream().anyMatch(o -> vo.getId().equals(o.getId()));
    }

    @Override
    public Children getByNameAndBirthday(String childrenName, Date birthday, String areaId) {
        return childrenRepository.findByNameAndBirthdayAndAreaId(childrenName, birthday, areaId);
    }

    @Override
    public Children getById(String id) {
        return childrenRepository.findById(id).orElse(null);
    }

    @Override
    public List<Children> getByIds(String[] childrenIds, String areaId) {
        return childrenRepository.findAllByAreaIdAndIdIn(areaId, childrenIds);
    }

    @Override
    public List<Children> getByIds(List<String> childrenIds, String areaId){
        return childrenRepository.findAllByAreaIdAndIdInAndStatus(areaId, childrenIds,1);
    }

    @Override
    public Children getByCrmClienteleId(String id) {
        return childrenRepository.findByCrmClienteleId(id);
    }

    @Override
    public Children getByIdAndAreaId(String id, String areaId) {
        return childrenRepository.findByIdAndAreaId(id, areaId);
    }

    @Override
    public Map childrenDetailById(String childrenId) {
        Children children = getById(childrenId);
        int yl = calculateBabyAgeInMonths(children.getBirthday());
        children.setMonth(yl);
        List<AppUserDetailVo> users = getAppUsersByChildrenId(childrenId);

        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);

        Map response = new HashMap();
        response.put("children", children);
        response.put("users", users);
        response.put("extend", extendInfo);

        return response;
    }



    // 计算宝宝月龄的方法
    public int calculateBabyAgeInMonths(Date birthday) {
        // 将Date转换为LocalDate
        LocalDate birthDate = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 计算两个日期之间的差值
        Period period = Period.between(birthDate, currentDate);
        // 计算总月龄
        int ageInMonths = period.getYears() * 12 + period.getMonths();
        return ageInMonths;
    }


    @Override
    public List<AppUserDetailVo> getAppUsersByChildrenId(String id) {
        List<Object[]> objects = userChildrenRepository.findByChildrenId(id);
        List<AppUserDetailVo> userList = objects.stream().map(o -> AppUserDetailVo.of(o)).collect(Collectors.toList());
        return userList;
    }

    @Transactional
    @Override
    public CheckRecord checkIn(StaffDTO staff, String childrenId) {
        Date now = new Date();

        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");

        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);

        Children children = childrenRepository.getOne(childrenId);
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        if (Objects.isNull(extendInfo)) {
            extendInfo = new ChildrenExtendInfo();
        } else {
            String chekcDate = DateUtil.formatDayToStr(extendInfo.getCheckTime());
            if (chekcDate.equals(currentDay)) {
                if (!extendInfo.getCheckStatus().equals(ChildrenConstant.CheckStatus.ABSENT.codeOf()) && !extendInfo.getCheckStatus().equals(ChildrenConstant.CheckStatus.LEFT.codeOf()))
                    throw new BusinessException(CHECK_STATUS_ERROR, "签到状态有误");
            }
        }

        extendInfo.setChildrenName(children.getName());
        extendInfo.setCheckStatus(ChildrenConstant.CheckStatus.JOIN.codeOf());
        extendInfo.setChildrenId(childrenId);
        extendInfo.setCheckTime(new Date());
        childrenExtendInfoRepository.save(extendInfo);
        int day = DateUtil.birthdayDay(end, begin) + 1;
        if (Objects.isNull(record)) {
            record = new CheckRecord();
            record.setCheckInTime(now);
            record.setCheckType(1);
            record.setCheckInStaffId(staff.getId());
            record.setChildrenId(childrenId);
            record.setCreated(now);
            record.setStatus(ChildrenConstant.CheckStatus.JOIN.codeOf());
            record.setCheckType(CommonConstant.Platform.WEB.codeOf());
            checkRecordRepository.save(record);
        }
        return record;
    }

    @Override
    public List<CheckRecord> getTodayCheckRecordByChilrenIds(List<String> childrenIdList) {
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        List<CheckRecord> recordList = checkRecordRepository.findAllByCheckInTimeBetweenAndChildrenIdIn(begin, end, childrenIdList);

        return recordList;
    }

    @Override
    public List<CheckRecord> getCheckRecordsByChilrenId(String areaId, String childrenId, String date) {
        List<CheckRecord> result = childrenCheckRecordRepository.findCheckRecordsByChildrenIdAndAreaIdAndDate(childrenId, areaId, date);
        return result;
    }

    @Transactional
    @OptsTrace(code = "0440")
    @Override
    public CheckRecord checkIn(AreaDTO area, StaffDTO staff, Integer checkType,
                               String childrenId, MultipartFile file, String sickName,
                               String specialRecord, String exceptionName, Integer healthyTag,
                               String weight, String height, String header, String remark) {
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);

        Children children = childrenRepository.getOne(childrenId);
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        if (Objects.isNull(extendInfo)) {
            extendInfo = new ChildrenExtendInfo();
        } else {
            if (null != extendInfo.getCheckTime()) {
                String chekcDate = DateUtil.formatDayToStr(extendInfo.getCheckTime());
                if (chekcDate.equals(currentDay) && extendInfo.getCheckStatus() == checkType)
                    throw new BusinessException(CHECK_STATUS_ERROR, "请勿重复签到");
            }

        }
        Integer checkStatus = ChildrenConstant.CheckStatus.JOIN.get(checkType).codeOf();

        extendInfo.setChildrenName(children.getName());
        extendInfo.setCheckStatus(checkStatus);
        extendInfo.setChildrenId(childrenId);
        extendInfo.setCheckTime(new Date());
        extendInfo.setHealthyStatus(healthyTag == null ? 0 : healthyTag);
        extendInfo.setSickName(sickName);
        extendInfo.setRemark(remark);
        childrenExtendInfoRepository.save(extendInfo);
        String image = "";
        if (Objects.isNull(record)) {
            record = new CheckRecord();
            record.setCheckInTime(now);
            record.setSpecialRecord(specialRecord);
            record.setExceptionName(exceptionName);
            record.setSickName(sickName);
            record.setHealthyStatus(healthyTag == null ? 0 : healthyTag);
            record.setHeight(StringUtils.isBlank(height) ? null : height);
            record.setWeight(StringUtils.isBlank(weight) ? null : weight);
            record.setHeader(header);

            if (Objects.nonNull(file)) {
                image = uploadService.uploadCheckInRecordImg(childrenId, file);
                record.setCheckInMediaUrl(image);
            }
            RelClassesChildren firstByChildrenId = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
            if (!Objects.isNull(firstByChildrenId)){
                record.setClassesId(firstByChildrenId.getClassesId());
            }

            record.setCheckType(CommonConstant.Platform.PAD.codeOf());
            record.setCheckInStaffId(staff.getId());
            record.setStatus(checkStatus);
            record.setChildrenId(childrenId);
            record.setCreated(now);
            checkRecordRepository.save(record);
        }

        String content = "";
        if (Objects.nonNull(healthyTag) && healthyTag != 0) {
            if (StringUtils.isNotBlank(exceptionName))
                content += String.format("%s异常 ", exceptionName);
            if (StringUtils.isNotBlank(specialRecord))
                content += String.format("%s ", specialRecord);
            if (StringUtils.isNotBlank(sickName))
                content += String.format("%s", sickName);
        }

        if (ChildrenConstant.CheckStatus.JOIN.codeOf() == checkType) {
            feedsService.save(staff.getId(), childrenId, staff.getAreaId(), FeedsConstant.CHECK_IN, FeedsConstant.HEALTH_CHECK, String.format("%s在%s签到", children.getName(), area.getName()), content, image, "", record.getId());
        } else if (ChildrenConstant.CheckStatus.LEAVE.codeOf() == checkType) {
            feedsService.save(staff.getId(), childrenId, staff.getAreaId(), FeedsConstant.LEAVE, FeedsConstant.HEALTH_CHECK, String.format("%s在%s请假", children.getName(), area.getName()), content, image, "", record.getId());
        }

        wxPushService.pushCheckInRecord(record, null);
        return record;
    }


    @Transactional
    @OptsTrace(code = "0440")
    @Override
    public CheckRecord checkIn(AreaDTO area, StaffDTO staff, Integer checkType,
                               String childrenId, MultipartFile file, String sickName,
                               String specialRecord, String exceptionName, Integer healthyTag,
                               String weight, String height, String header, String remark, Integer dayAmount, Integer isHoliday, String ticket) {
        if (Objects.isNull(dayAmount)) {
            dayAmount = 1;
        }
        System.out.println("-------------------------------------------------------------进入到签到");
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);

        Children children = childrenRepository.getOne(childrenId);
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        if (Objects.isNull(extendInfo)) {
            extendInfo = new ChildrenExtendInfo();
        } else {
            if (null != extendInfo.getCheckTime()) {
                String chekcDate = DateUtil.formatDayToStr(extendInfo.getCheckTime());
                if (chekcDate.equals(currentDay) && extendInfo.getCheckStatus() == checkType)
                    throw new BusinessException(CHECK_STATUS_ERROR, "请勿重复签到");
            }

        }
        Integer checkStatus = ChildrenConstant.CheckStatus.JOIN.get(checkType).codeOf();

        extendInfo.setChildrenName(children.getName());
        extendInfo.setCheckStatus(checkStatus);
        extendInfo.setChildrenId(childrenId);
        extendInfo.setCheckTime(new Date());
        extendInfo.setHealthyStatus(healthyTag == null ? 0 : healthyTag);
        extendInfo.setSickName(sickName);
        extendInfo.setRemark(remark);
        childrenExtendInfoRepository.save(extendInfo);
        String image = "";
        if (Objects.isNull(record)) {
            record = new CheckRecord();
            record.setCheckInTime(now);
            record.setSpecialRecord(specialRecord);
            record.setExceptionName(exceptionName);
            record.setSickName(sickName);
            record.setHealthyStatus(healthyTag == null ? 0 : healthyTag);
            record.setHeight(StringUtils.isBlank(height) ? null : height);
            record.setWeight(StringUtils.isBlank(weight) ? null : weight);
            record.setHeader(header);

            if (Objects.nonNull(file)) {
                image = uploadService.uploadCheckInRecordImg(childrenId, file);
                record.setCheckInMediaUrl(image);
            }

            record.setCheckType(CommonConstant.Platform.PAD.codeOf());
            record.setCheckInStaffId(staff.getId());
            record.setStatus(checkStatus);
            record.setChildrenId(childrenId);
            record.setCreated(now);
            checkRecordRepository.save(record);

            generateCheckLogs(staff, children, extendInfo, checkType, checkStatus, healthyTag, begin, end, remark, dayAmount, isHoliday);
        }
        String content = "";
        if (Objects.nonNull(healthyTag) && healthyTag != 0) {
            if (StringUtils.isNotBlank(exceptionName))
                content += String.format("%s异常 ", exceptionName);
            if (StringUtils.isNotBlank(specialRecord))
                content += String.format("%s ", specialRecord);
            if (StringUtils.isNotBlank(sickName))
                content += String.format("%s", sickName);
        }

        if (ChildrenConstant.CheckStatus.JOIN.codeOf() == checkType) {
            feedsService.save(staff.getId(), childrenId, staff.getAreaId(), FeedsConstant.CHECK_IN, FeedsConstant.HEALTH_CHECK, String.format("%s在%s签到", children.getName(), area.getName()), content, image, "", record.getId());
        } else if (ChildrenConstant.CheckStatus.LEAVE.codeOf() == checkType) {
            feedsService.save(staff.getId(), childrenId, staff.getAreaId(), FeedsConstant.LEAVE, FeedsConstant.HEALTH_CHECK, String.format("%s在%s请假", children.getName(), area.getName()), content, image, "", record.getId());
        }


        wxPushService.pushCheckInRecord(record, null);
        return record;
    }

    private void generateCheckLogs(StaffDTO staff, Children children, ChildrenExtendInfo extendInfo,
                                   Integer checkType, Integer checkStatus, Integer healthyTag,
                                   Date begin, Date end, String remark, Integer dayAmount, Integer isHoliday){

        ChildrenNurseryInfoRecord childrenNurseryInfoRecord = new ChildrenNurseryInfoRecord();
        childrenNurseryInfoRecord.setChildrenId(children.getId());
        childrenNurseryInfoRecord.setCreatedName(children.getName());
        childrenNurseryInfoRecord.setStatus(checkStatus);
        childrenNurseryInfoRecord.setHealthyStatus(healthyTag == null ? 0 : healthyTag);
        childrenNurseryInfoRecord.setBeginDate(begin);
        childrenNurseryInfoRecord.setEndDate(end);

        //请假天数 +1
        int day = DateUtil.betweenDay(end, begin) + 1;

        //顺延日期
        WorkDate workDate = workDateRepository.getWorkDateAscDay(extendInfo.getNurseryEndDate(), day);

        List<ChildrenNurseryInfoRecord> list = childrenNurseryInfoRecordRepository.findAllByAndChildrenIdTime(children.getId(), end, begin);

        if (list.size() != 0){
            if (checkType == 5) {
                throw new BusinessException(CHECK_STATUS_ERROR, "宝宝当天产生消课记录！当天不能出现重复记录！");
            }
            return;
        }

        if (checkStatus == ChildrenConstant.CheckStatus.LEAVE.codeOf()) {
            System.out.println("--------------------请假-----------------------------------------进入到请假签到");
            if (Objects.isNull(extendInfo)) {
                return;
            }

            //可延长天数必须大于0
            if (day > 0) {
                if (dayAmount > 0) {
                    day = dayAmount;
                }
                //添加考勤流水记录
                childrenNurseryInfoRecord.setEffectDay(day);
                childrenNurseryInfoRecord.setType(ChildrenConstant.SurplusType.EXTENDED_RECORDS.codeOf());

                if (AssertUtil.isNotEmpty(workDate)) {
                    childrenNurseryInfoRecord.setNurseryEndDate(workDate.getWorkDate());
                } else {
                    childrenNurseryInfoRecord.setNurseryEndDate(DateUtil.addDay(extendInfo.getNurseryEndDate(), day));
                }

                childrenNurseryInfoRecord.setRemark("请假：" + staff.getRealName() + "老师手动请假" + day + "天;" + remark);

                childrenNurseryInfoRecord.setNurseryOriginalEndDate(extendInfo.getNurseryEndDate());

                childrenNurseryInfoRecord.setCreatedBy(staff.getId());
                childrenNurseryInfoRecord.setCreatedName(staff.getRealName());

                //修改合同请假天数
                List<ChildrenContractInfoRecord> contractInfoRecordList = getChildrenContractInfoRecord( staff, children.getId(), begin, day, 1);

                if (contractInfoRecordList.size() > 0) {
                    childrenNurseryInfoRecordRepository.save(childrenNurseryInfoRecord);
                    //修改宝宝合同日期
                    extendInfo.setNurseryEndDate(childrenNurseryInfoRecord.getNurseryEndDate());
                    childrenExtendInfoRepository.save(extendInfo);
                } else {
                    throw new BusinessException(CHECK_STATUS_ERROR, "合同未生效！");
                }
            }
        } else {
            System.out.println("--------------------打卡-----------------------------------------进入到打卡签到");
            //添加考勤流水记录
            childrenNurseryInfoRecord.setEffectDay(day);
            childrenNurseryInfoRecord.setType(ChildrenConstant.SurplusType.ORDINARY.codeOf());
            childrenNurseryInfoRecord.setNurseryEndDate(extendInfo.getNurseryEndDate());
            childrenNurseryInfoRecord.setSurplusOriginalLeaveDay(extendInfo.getSurplusLeaveDay());
            childrenNurseryInfoRecord.setSurplusLeaveDay(extendInfo.getSurplusLeaveDay());
            childrenNurseryInfoRecord.setNurseryOriginalEndDate(extendInfo.getNurseryEndDate());
            childrenNurseryInfoRecord.setCreatedBy(staff.getId());
            childrenNurseryInfoRecord.setCreatedName(staff.getRealName());
            childrenNurseryInfoRecord.setSurplusOriginalLeaveDay(extendInfo.getSurplusLeaveDay());
            childrenNurseryInfoRecord.setSurplusLeaveDay(extendInfo.getSurplusLeaveDay());

            if (AssertUtil.isEmpty(isHoliday)) {
                isHoliday = 0;
            }

            if ((checkType == 5 && dayAmount > 1) || (checkType == 5 && dayAmount == 1 && isHoliday == 1)) {
                //合同提前与延长标识
                int count;

                if (isHoliday == 1 || StringUtils.equals(String.valueOf(isHoliday), "1")) {
                    count = dayAmount ;
                    childrenNurseryInfoRecord.setRemark("节假日：" + staff.getRealName() + "老师手动消课" + dayAmount + "天;" + remark);
                } else {
                    count = (dayAmount - 1);
                    childrenNurseryInfoRecord.setRemark("工作日：" + staff.getRealName() + "老师手动消课" + dayAmount + "天;" + remark);
                }
                childrenNurseryInfoRecord.setType(ChildrenConstant.SurplusType.REGISTER_BUCKLE.codeOf());
                childrenNurseryInfoRecord.setEffectDay(dayAmount);
                WorkDate workDate1 = workDateRepository.getWorkDateDescDay(extendInfo.getNurseryEndDate(), count - 1);
                if (AssertUtil.isNotEmpty(workDate)) {
                    childrenNurseryInfoRecord.setNurseryEndDate(workDate1.getWorkDate());
                } else {
                    childrenNurseryInfoRecord.setNurseryEndDate(DateUtil.addDay(extendInfo.getNurseryEndDate(), (~(count - 1))));
                }

                //修改合同请假天数
                List<ChildrenContractInfoRecord> contractInfoRecordList = getChildrenContractInfoRecord( staff, children.getId(), begin, (~(count - 1)), 2);
                if (contractInfoRecordList.size() > 0) {
                    childrenNurseryInfoRecordRepository.save(childrenNurseryInfoRecord);
                    //修改宝宝合同日期
                    extendInfo.setNurseryEndDate(childrenNurseryInfoRecord.getNurseryEndDate());
                    childrenExtendInfoRepository.save(extendInfo);
                } else {
                    throw new BusinessException(CHECK_STATUS_ERROR, "合同未生效！");
                }

            } else {
                childrenNurseryInfoRecord.setRemark("打卡：" + staff.getRealName() + "老师打卡记录");
                childrenNurseryInfoRecordRepository.save(childrenNurseryInfoRecord);
            }
        }
    }


    @Transactional
    @Override
    public CheckRecord checkOut(String staffId, String childrenId) {
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);
        if (Objects.isNull(record))
            throw new BusinessException(CHECK_IN_RECORD_NON, "没有签到记录");

        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);

        if (!extendInfo.getCheckStatus().equals(ChildrenConstant.CheckStatus.JOIN.codeOf()))
            throw new BusinessException(CHECK_STATUS_ERROR, "签到状态有误");

        extendInfo.setCheckStatus(ChildrenConstant.CheckStatus.LEFT.codeOf());

        extendInfo.setChildrenId(childrenId);
        extendInfo.setCheckTime(new Date());
        childrenExtendInfoRepository.save(extendInfo);

        record.setCheckOutTime(now);
        record.setCheckOutStaffId(staffId);
        record.setStatus(ChildrenConstant.CheckStatus.LEFT.codeOf());
        Long duration = DateUtil.betweetMillis(record.getCheckInTime(), now);
        record.setDuration(BigInteger.valueOf(duration < 0L ? 0L : duration));
        checkRecordRepository.save(record);


        return record;
    }

    @Transactional
    @Override
    public CheckRecord checkOut(StaffDTO staff, AreaDTO area, String childrenId, MultipartFile file) {
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);
        if (Objects.isNull(record))
            throw new BusinessException(CHECK_IN_RECORD_NON, "没有签到记录");

        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);

        if (!extendInfo.getCheckStatus().equals(ChildrenConstant.CheckStatus.JOIN.codeOf()))
            throw new BusinessException(CHECK_STATUS_ERROR, "签到状态有误,无签到记录");

        extendInfo.setCheckStatus(ChildrenConstant.CheckStatus.LEFT.codeOf());

        extendInfo.setChildrenId(childrenId);
        extendInfo.setCheckTime(new Date());
        childrenExtendInfoRepository.save(extendInfo);
        String image = "";
        if (Objects.nonNull(file)) {
            image = uploadService.uploadCheckOutRecordImg(childrenId, file);
            record.setCheckOutMediaUrl(image);
        }


        record.setCheckOutTime(now);
        record.setCheckOutStaffId(staff.getId());
        Long duration = DateUtil.betweetMillis(record.getCheckInTime(), now);
        record.setStatus(ChildrenConstant.CheckStatus.LEFT.codeOf());
        record.setDuration(BigInteger.valueOf(duration < 0L ? 0L : duration));
        checkRecordRepository.save(record);

        //Time Line ====begin
        Children children = childrenRepository.getOne(childrenId);

        feedsService.save(staff.getId(), childrenId, area.getId(), FeedsConstant.CHECK_OUT, FeedsConstant.HEALTH_CHECK, String.format("%s在%s离园", children.getName(), area.getName()), "", image, "", record.getId());
        //Time Line ====end

        wxPushService.pushCheckOutRecord(childrenId, null);
        return record;
    }

    @Override
    public CheckRecord cancelCheckInRecord(StaffDTO staff, String childrenId, String date){

        String areaId = staff.getAreaId();
        Children c = childrenRepository.findByIdAndAreaId(childrenId, areaId);

        if (c == null){
            throw new BusinessException(CHILDREN_NOT_EXIST, "指定宝宝不存在");
        }

        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(date);
        Date begin = map.get("beg");
        Date end = map.get("end");

        CheckRecord ret = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndStatus(begin, end, childrenId, ChildrenConstant.CheckStatus.REJECTED.codeOf());

        if (ret == null){
            throw new BusinessException(MATERIAL_NOT_EXIST, "没有找到对应的签到记录");
        }
        checkRecordRepository.delete(ret);
        ChildrenNurseryInfoRecord childrenNurseryInfoRecord = childrenNurseryInfoRecordRepository.findByChildrenIdAndBeginDateAndStatus(childrenId,begin, end,3);
        if (null != childrenNurseryInfoRecord){
            childrenNurseryInfoRecordRepository.delete(childrenNurseryInfoRecord);
        }

        ChildrenExtendInfo extendInfo = extendInfoRepository.findByChildrenId(childrenId);
        extendInfo.setCheckStatus(0);
        extendInfo.setHealthyStatus(0);

        extendInfoRepository.save(extendInfo);

        return ret;
    }

    //  PAD端分班级的签到列表  园区属性未做强判断
    @Override
    public List<ClassesCheckRecordVo> findClassesCheckRecordByAreaId(String areaId) {
        System.out.println("classes.areaId:" + areaId);
        String today = DateUtil.formatDayToStr(new Date());
        List<Classes> classes = classesRepository.findByAreaIdAndCategoryAndDeleted(areaId, CourseConstant.Category.NURSERY.codeOf(), false);
        System.out.println("classes.szieL:" + classes.size());

        if (classes == null || classes.size() == 0) {
            return new ArrayList<>();
        }

        List<String> classIds = classes.stream().map(k -> k.getId()).collect(Collectors.toList());
        List<ChildrenCheckRecordDO> fullCheckRecords = childrenCheckRecordRepository.findByClassesIn(classIds);
        if (fullCheckRecords == null || fullCheckRecords.size() == 0) {
            return new ArrayList<>();
        }

        Map<String, List<ChildrenCheckRecordDO>> cache = new HashMap<>();
        for (ChildrenCheckRecordDO d : fullCheckRecords) {
            List<ChildrenCheckRecordDO> items = cache.get(d.getClassesId());
            if (items == null) {
                items = new ArrayList<>();
                cache.put(d.getClassesId(), items);
            }

            int checkStatus = d.getCheckStatus() == null ? 0 : d.getCheckStatus(); //0 -"未签到" 1-"入园" 2-"离园" 3-"拒绝入园" 4-"请假"
            if (d.getCheckTime() != null) {
                String checkDate = DateUtil.formatDayToStr(d.getCheckTime());
                if ((checkStatus == ChildrenConstant.CheckStatus.REJECTED.codeOf() || checkStatus == ChildrenConstant.CheckStatus.LEAVE.codeOf() || checkStatus == ChildrenConstant.CheckStatus.JOIN.codeOf()) && !checkDate.equals(today)) {
                    d.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
                }
            } else {
                if ((checkStatus == ChildrenConstant.CheckStatus.REJECTED.codeOf() || checkStatus == ChildrenConstant.CheckStatus.LEAVE.codeOf())) {
                    d.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
                }
            }

            items.add(d);
        }

        List<ClassesCheckRecordVo> classesVoList = Lists.newArrayList();
        classes.forEach(c -> {
            List<ChildrenCheckRecordDO> doList = cache.get(c.getId());
            if (doList == null || doList.size() == 0) {
                return;
            }
            //FIXME: What the fuck?
            List<ChildrenCheckRecordVo> voList = doList.stream().map(o -> ChildrenCheckRecordVo.of(o)).collect(Collectors.toList());
            ClassesCheckRecordVo vo = ClassesCheckRecordVo.of(c.getName(), voList);
            classesVoList.add(vo);
        });

        return classesVoList;
    }

    @Override
    public List<ClassesCheckRecordVo> findClassesCheckRecordByClassId(String classId) {

        if (StringUtils.isEmpty(classId)) {
            return new ArrayList<>();
        }

        Date today = new Date();

        String todayStr = DateUtil.formatDayToStr(today);

        List<ClassesCheckRecordVo> classesVoList = Lists.newArrayList();
        Classes classes = classesRepository.getOne(classId);
        List<ChildrenCheckRecordDO> doList = childrenCheckRecordRepository.findByClasses(classId);

        doList.forEach(v -> {
            //月龄
            String birthday = DateUtil.formatDayToStr(v.getBirthday());
            try {
                Integer monthInterval = DateUtil.betweenMonths(DateUtil.millisToDateTime(today.getTime(), "yyyy-MM-dd"), birthday);//月龄
                v.setMonth(monthInterval);
            } catch (ParseException e) {
                throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
            }

            //出缺勤状态
            int checkStatus = v.getCheckStatus() == null ? 0 : v.getCheckStatus(); //0 -"未签到" 1-"入园" 2-"离园" 3-"拒绝入园" 4-"请假"
            if (v.getCheckTime() != null) {
                String checkDate = DateUtil.formatDayToStr(v.getCheckTime());
                if (!checkDate.equals(todayStr) && checkStatus != ChildrenConstant.CheckStatus.LEAVE.codeOf() && checkStatus != ChildrenConstant.CheckStatus.REJECTED.codeOf()) {
                    v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
                }
            } else {
                v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
            }
        });

        List<ChildrenCheckRecordVo> voList = doList.stream().map(o -> ChildrenCheckRecordVo.of(o)).collect(Collectors.toList());
        ClassesCheckRecordVo vo = ClassesCheckRecordVo.of(classes.getName(), voList);
        classesVoList.add(vo);

        return classesVoList;
    }

    @Override
    public List<ClassesCheckRecordVo> findClassesCheckRecordByClassId(String classId, Date date) {
        if (StringUtils.isEmpty(classId)) {
            return new ArrayList<>();
        }

        Date today = date;

        String todayStr = DateUtil.formatDayToStr(today);

        List<ClassesCheckRecordVo> classesVoList = Lists.newArrayList();
        Classes classes = classesRepository.getOne(classId);
        List<ChildrenCheckRecordDO> doList = childrenCheckRecordRepository.findByClassesAndCreated(classId,todayStr);

        doList.forEach(v -> {
            //月龄
            String birthday = DateUtil.formatDayToStr(v.getBirthday());
            try {
                Integer monthInterval = DateUtil.betweenMonths(DateUtil.millisToDateTime(new Date().getTime(), "yyyy-MM-dd"), birthday);//月龄
                v.setMonth(monthInterval);
            } catch (ParseException e) {
                throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
            }

            //出缺勤状态
            int checkStatus = v.getCheckStatus() == null ? 0 : v.getCheckStatus(); //0 -"未签到" 1-"入园" 2-"离园" 3-"拒绝入园" 4-"请假"
            if (v.getCheckTime() != null) {
                String checkDate = DateUtil.formatDayToStr(v.getCheckTime());
                if (!checkDate.equals(todayStr) || (!checkDate.equals(todayStr) && checkStatus != ChildrenConstant.CheckStatus.LEAVE.codeOf() && checkStatus != ChildrenConstant.CheckStatus.REJECTED.codeOf())) {
                    v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
                }
            } else {
                v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
            }
        });

        List<ChildrenCheckRecordVo> voList = doList.stream().map(o -> ChildrenCheckRecordVo.of(o)).collect(Collectors.toList());
        ClassesCheckRecordVo vo = ClassesCheckRecordVo.of(classes.getName(), voList);
        classesVoList.add(vo);

        return classesVoList;
    }


    @Override
    public List<ClassesCheckRecordVo> findStaffCheckRecord(List<String> staffIds, Date beginDate, Date endDate) {
        if (staffIds == null || staffIds.size() == 0) {
            return new ArrayList<>();
        }

        List<ChildrenCheckRecordDO> doList = childrenCheckRecordRepository.findByChildrenIdsAndCreated(staffIds, beginDate, endDate);

        doList.stream().filter(o->o.getCheckStatus()==null).forEach(v -> {
            v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
        });


//        List<ClassesCheckRecordVo> classesVoList = new ArrayList<>();

        List<ChildrenCheckRecordVo> childrenList = doList.stream().map(o -> ChildrenCheckRecordVo.of(o)).collect(Collectors.toList());

        ClassesCheckRecordVo vo = ClassesCheckRecordVo.of("", childrenList);

        return Arrays.asList(vo);
    }

    @Override
    public List<ClassesCheckRecordVo> findClassesCheckRecordByClasses(List<ClassListDO> classes) {

        String today = DateUtil.formatDayToStr(new Date());

        System.out.println("check records for classes.szieL:" + classes.size());

        if (classes == null || classes.size() == 0) {
            return new ArrayList<>();
        }

        List<String> classIds = classes.stream().map(k -> k.getId()).collect(Collectors.toList());
        List<ChildrenCheckRecordDO> doList = childrenCheckRecordRepository.findByClassesIn(classIds);


        List<ClassesCheckRecordVo> classesVoList = Lists.newArrayList();
        classes.forEach(c -> {
            if (doList == null || doList.size() == 0) {
                return;
            }
            //FIXME: What the fuck?
            String todayStr = DateUtil.formatDayToStr(new Date());
            doList.forEach(v -> {
                //月龄
                String birthday = DateUtil.formatDayToStr(v.getBirthday());
                try {
                    Integer monthInterval = DateUtil.betweenMonths(DateUtil.millisToDateTime(new Date().getTime(), "yyyy-MM-dd"), birthday);//月龄
                    v.setMonth(monthInterval);
                } catch (ParseException e) {
                    throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
                }

                //出缺勤状态
                //0 -"未签到" 1-"入园" 2-"离园" 3-"拒绝入园" 4-"请假"
                int checkStatus = v.getCheckStatus() == null ? 0 : v.getCheckStatus();
                if (v.getCheckTime() != null) {
                    String checkDate = DateUtil.formatDayToStr(v.getCheckTime());
                    if (!checkDate.equals(todayStr) || (!checkDate.equals(todayStr) && checkStatus != ChildrenConstant.CheckStatus.LEAVE.codeOf() && checkStatus != ChildrenConstant.CheckStatus.REJECTED.codeOf())) {
                        v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
                    }
                } else {
                    v.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.codeOf());
                }
            });

            List<ChildrenCheckRecordVo> voList = doList.stream()
                    .filter(o -> c.getId().equals(o.getClassesId()))
                    .map(o -> ChildrenCheckRecordVo.of(o))
                    .collect(Collectors.toList());
            ClassesCheckRecordVo vo = ClassesCheckRecordVo.of(c.getName(), voList);
            classesVoList.add(vo);
        });

        return classesVoList;
    }


    @Override
    public List<ChildrenCheckRecordDO> findChildCheckRecordByClasses(String classesId) {
        List<ChildrenCheckRecordDO> doList = childrenCheckRecordRepository.findByClasses(classesId);
        return doList;
    }

    @Override
    public List<ClassesChildrenListVo> getChildrenByClasses(String classesId) {
        List<Object[]> objects = classesChildrenRepository.findChildrenByClasses(classesId);
        List<ClassesChildrenListVo> childrenList = objects.stream().map(o -> ClassesChildrenListVo.of(o)).collect(Collectors.toList());
        return childrenList;
    }

    @Override
    public List<ClassesChildrenListVo> findClassHourChildrenByClasses(String classesId) {
        List<Object[]> objects = classesChildrenRepository.findClassHourChildrenByClasses(classesId);
        List<ClassesChildrenListVo> childrenList = objects.stream().map(o -> ClassesChildrenListVo.of(o)).collect(Collectors.toList());
        return childrenList;
    }

    @Override
    public Map getChildMediaStatisticsInfo(String childrenId) {
        List<Object[]> objects = childrenLiveRecordRepository.findRecordsByChildren(childrenId);
        Integer imageNum = 0;
        Integer videoNum = 0;
        for (Object[] o : objects) {
            if ((Integer) o[1] == LiveRecordConstant.MediaType.IMG.codeOf())
                imageNum++;
            else
                videoNum++;


        }
        return ImmutableMap.of("imageNum", imageNum, "videoNum", videoNum, "recordNum", imageNum + videoNum);
    }

    @Transactional
    @OptsTrace(code = "0100")
    @Override
    public Children dropOut(StaffDTO staff, String childrenId, String reason, String backMoney) {
        Children children = childrenRepository.getOne(childrenId);
        if (ChildrenConstant.ChildrenStatus.GRADUATED.codeOf() == children.getStatus() || ChildrenConstant.ChildrenStatus.DROP_OUT.codeOf() == children.getStatus())
            throw new BusinessException(ErrorCode.CHILDREN_STATUS_ERROR, "该宝宝已经毕业或退学");
        overNursery(staff, childrenId, String.format("手动退学:理由[%s]", reason));
        overEarly(staff, childrenId, String.format("手动退学:理由[%s]", reason));
        children.setStatus(ChildrenConstant.ChildrenStatus.DROP_OUT.codeOf());
        children.setBackMoney(new BigDecimal(backMoney));

        Date date = new Date();
        // 创建SimpleDateFormat对象并指定格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 格式化Date对象
        String formattedDate = sdf.format(date);
        children.setStatusRemark("宝宝在"+formattedDate+","+"就学状态变更为退学！");
        childrenRepository.save(children);

        return children;
    }

    @Transactional
    @OptsTrace(code = "0101")
    @Override
    public Children graduate(StaffDTO staff, String areaId, String childrenId) {
        Children children = childrenRepository.getOne(childrenId);
        if (ChildrenConstant.ChildrenStatus.GRADUATED.codeOf() == children.getStatus() || ChildrenConstant.ChildrenStatus.DROP_OUT.codeOf() == children.getStatus())
            throw new BusinessException(ErrorCode.CHILDREN_STATUS_ERROR, "该宝宝已经毕业或退学");
        overNursery(staff, childrenId, "手动毕业");
        overEarly(staff, childrenId, "手动毕业");
        children.setStatus(ChildrenConstant.ChildrenStatus.GRADUATED.codeOf());
        Date date = new Date();
        // 创建SimpleDateFormat对象并指定格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 格式化Date对象
        String formattedDate = sdf.format(date);
        children.setStatusRemark("宝宝在"+formattedDate+","+"就学状态变更为毕业！");
        childrenRepository.save(children);

        return children;
    }

    @Override
    public List<ChildrenListVo> getEvaluatingCBBindList(String areaId, String name) {
        List<Object[]> children = childChildrenExtendRepository.findChildrenByCBNonBind(areaId, name);
        List<ChildrenListVo> childrenList = children.stream().map(o -> ChildrenListVo.of(o)).collect(Collectors.toList());
        return childrenList;
    }

    @Transactional
    @OptsTrace(code = "0304")
    @Override
    public Boolean bindEvaluatingCB(String evaluatingCBRecordId, String childrenId) {
//        EvaluatingCBRecord record = evaluatingCBRecordRepository.getOne(evaluatingCBRecordId);
//        if (record.getStatus() != EvaluatingConstant.CBSRecordStatus.ASSESS.codeOf())
//            throw new BusinessException(ErrorCode.EVALUATING_CB_STATUS_ERROR, "该初评结果还未评估，无法绑定宝宝");
//        record.setStatus(EvaluatingConstant.CBSRecordStatus.BIND.codeOf());
//        record.setChildrenId(childrenId);
//        evaluatingCBRecordRepository.save(record);
//        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
//        extendInfo.setEvaluatingCBBindStatus(ChildrenConstant.EvaluatingCBBindStatus.BIND.codeOf());
//        childrenExtendInfoRepository.save(extendInfo);
        return true;
    }


    @Transactional
    @Override
    public Boolean overNursery(StaffDTO staff, String childrenId, String remark) {
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        extendInfo.setNurseryStatus(ChildrenConstant.NurseryStatus.ALL_COURSE_OVER.codeOf());
        childrenExtendInfoRepository.save(extendInfo);
        //清楚所有早教班级
        relClassesChildrenRepository.deleteByChildrenId(childrenId);
        checkAllContractOver(childrenId);
        return true;
    }

    //检查是否所有合同结束
    public Boolean checkAllContractOver(String childrenId) {
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        if (extendInfo.getEarlyLeftCourseNum() <= 0 && extendInfo.getNurseryStatus() <= 0) {
            Children children = childrenRepository.getOne(childrenId);
            children.setStatus(ChildrenConstant.ChildrenStatus.END.codeOf());
            childrenRepository.save(children);
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean overEarly(StaffDTO staff, String childrenId, String remark) {
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);

        //处理早教课时
        Integer leftCourseSize = extendInfo.getEarlyLeftCourseNum();
        extendInfo.setEarlyLeftCourseNum(0);

        //添加消课记录
        ChildrenCourseChangeRecord record = ChildrenCourseChangeRecord.of(staff.getId(), childrenId, remark, -leftCourseSize, 0, staff.getRealName());
        childrenCourseChangeRecordRepository.save(record);
        checkAllContractOver(childrenId);
        return true;
    }

    @Transactional
    @Override
    public Boolean changeEarlyCourseCount(StaffDTO staff, String childrenId, Integer courseCount, String remark) {
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);

        //处理早教课时
        Integer leftCourseSize = extendInfo.getEarlyLeftCourseNum() + courseCount;
        extendInfo.setEarlyLeftCourseNum(leftCourseSize);

        //添加消课记录
        ChildrenCourseChangeRecord record = ChildrenCourseChangeRecord.of(staff.getId(), childrenId, remark, courseCount, leftCourseSize, staff.getRealName());
        childrenCourseChangeRecordRepository.save(record);
        checkAllContractOver(childrenId);
        return true;
    }

    @Override
    public List<ChildrenListDO> getNurseryChildByAppUser(String userId) {
        return userChildrenRepository.findNurseryChild(userId);
    }

    @Override
    public CheckRecord getLastCheckRecord(String childrenId) {
        List<CheckRecord> checkRecordList = checkRecordRepository.findByChildrenId(childrenId);
        return checkRecordList.isEmpty() ? null : checkRecordList.get(0);
    }

    @Override
    public Page<WebChildrenVo> page(ChildrenQuery query) {

        List<WebChildrenVo> list = childrenNativeRepository.findByQueryNew(query, true);
        Long count = childrenNativeRepository.findCountByQueryNew(query);
        setChildrenInfo(list);
        return new PageImpl<>(list, PageRequest.of(query.getPageNum(), query.getPageSize()), count);
    }

    /**
     * 给导出使用的方法,@Page 两个方法保持一致
     *
     * @param query
     * @return
     */
    @Override
    public List<WebChildrenVo> nonPage(ChildrenQuery query) {
        List<WebChildrenVo> list = childrenNativeRepository.findByQueryNew(query, false);
        setChildrenInfo(list);
        return list;
    }


    private void setChildrenInfo(List<WebChildrenVo> list) {

        List<String> childrenIds = list.stream().map(k -> k.getId()).collect(Collectors.toList());
        Map<String, Integer> countResult = childrenNativeRepository.findEarlyPlanCourseNumByChildrenIds(childrenIds);
        for (WebChildrenVo webChildrenVo : list) {
            Integer courseNum = countResult.get(webChildrenVo.getId());
            webChildrenVo.setEarlyPlanCourseNum(courseNum == null ? 0 : courseNum);
            webChildrenVo.setMonth(DateUtil.betweenMonths(new Date(), webChildrenVo.getBirthday()));
        }
    }

    /*
     * 2019-01-10发现此方法未使用
     * */
//    @Override
//    public Children detailBaseInfo(String ticket, String childrenId) {
//        return childrenRepository.getOne(childrenId);
//    }

    @Override
    @Transactional
    public AppUserDetailVo updateChildrenLinkMans(String childrenId, ParentUser parentUser) {

        Children children = childrenRepository.getOne(childrenId);
        if (Objects.isNull(children))
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在！");


        //查找关系
        RelUserChildren rel = relUserChildrenRepository.findByChildrenIdAndUserIdAndId(childrenId, parentUser.getId(), parentUser.getRid());
        if (rel == null) {
            throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "参数错误！");
        }

        rel.setCameraEnabled(parentUser.getCameraEnabled());
        rel.setWechatEnabled(parentUser.getWechatEnabled());
        rel.setTemplateMsgEnabled(parentUser.getTemplateMsgEnabled());
        rel.setTeacherChatEnabled(parentUser.getTeacherChatEnabled());

        ParentUser save = appUserRepository.getById(parentUser.getId());
        if (save == null) {
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "联系人不存在");
        }

        appUserRepository.save(save);

        AppUserDetailVo of = AppUserDetailVo.of(new Object[]{save.getId(), rel.getId(), save.getName(), save.getPhone(), save.getCompany(), save.getEmail(), parentUser.getRelation(), parentUser.getRemark()});
        of.setCameraEnabled(parentUser.getCameraEnabled());
        of.setWechatEnabled(parentUser.getWechatEnabled());
        of.setTemplateMsgEnabled(parentUser.getTemplateMsgEnabled());
        of.setTeacherChatEnabled(parentUser.getTeacherChatEnabled());

        return of;
    }

    @Override
    @Transactional
    public AppUserDetailVo addChildrenLinkMans(String childrenId, ParentUser parentUser) {
        Children children = childrenRepository.getOne(childrenId);
        if (Objects.isNull(children))
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在！");

        if (StringUtils.isBlank(parentUser.getId())) {
            //宝宝对应的手机号是否存在  新增才验证
            ParentUser byCidAndPhone = appUserRepository.findByCidAndPhone(childrenId, parentUser.getPhone());
            if (byCidAndPhone != null)
                throw new BusinessException(ErrorCode.MOBILE_IS_EXIST, "手机号已存在！");
        }
        String relationId = parentUser.getRid();//关系表主键ID
        //查询此手机号是否存在
        ParentUser save = appUserRepository.findByPhone(parentUser.getPhone());
        if (save == null) {
            save = appUserRepository.save(parentUser);
        } else {
            parentUser.setId(save.getId());
            parentUser.setCreated(save.getCreated());
            save = appUserRepository.saveAndFlush(parentUser);
        }

        if (StringUtils.isNotBlank(parentUser.getRid())) {
            //更新关系
            RelUserChildren one = relUserChildrenRepository.getOne(parentUser.getRid());
            one.setRelation(parentUser.getRelation());
            one.setRemark(parentUser.getRemark());

            //更新配置
            one.setCameraEnabled(parentUser.getCameraEnabled());
            one.setTeacherChatEnabled(parentUser.getTeacherChatEnabled());
            one.setTemplateMsgEnabled(parentUser.getTemplateMsgEnabled());
            one.setWechatEnabled(parentUser.getWechatEnabled());

            RelUserChildren relUserChildren = relUserChildrenRepository.saveAndFlush(one);
            relationId = relUserChildren.getId();
        } else {
            // 增加关系
            RelUserChildren of = RelUserChildren.of(save.getId(), childrenId, parentUser.getRelation(), parentUser.getRemark());
            //保存配置
            of.setCameraEnabled(parentUser.getCameraEnabled());
            of.setTeacherChatEnabled(parentUser.getTeacherChatEnabled());
            of.setTemplateMsgEnabled(parentUser.getTemplateMsgEnabled());
            of.setWechatEnabled(parentUser.getWechatEnabled());

            RelUserChildren save1 = relUserChildrenRepository.save(of);
            relationId = save1.getId();
        }
        AppUserDetailVo of = AppUserDetailVo.of(new Object[]{
                save.getId(),
                relationId,
                save.getName(),
                save.getPhone(),
                save.getCompany(),
                save.getEmail(),
                parentUser.getRelation(),
                parentUser.getRemark(),
                //响应配置
                parentUser.getCameraEnabled(),
                parentUser.getWechatEnabled(),
                parentUser.getTemplateMsgEnabled(),
                parentUser.getTeacherChatEnabled()
        });

        return of;
    }

    @Override
    @Transactional
    public boolean delChildrenLinkMans(String childrenId, String id) {
        try {
            Children children = childrenRepository.getOne(childrenId);
            if (Objects.isNull(children))
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在！");
            relUserChildrenRepository.deleteByChildrenIdAndUserId(childrenId, id);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public List<CheckRecord> getLastCheckRecord(List<String> childrenId) {
        return null;
    }

    @Override
    public String getClassesByChildrenId(String childrenId) {
        String classId = null;
        RelClassesChildren relClassesChildren = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
        if (null != relClassesChildren) {
            classId = relClassesChildren.getClassesId();
        }
        return classId;
    }

    @Override
    public List<ChildrenCheckRecordVo> findCheckRecordByAreaId(String areaId) {

        Date today = new Date();

        List<ChildrenCheckRecordDO> doList = childrenCheckRecordRepository.findByAreaId(areaId);

        doList.forEach(v -> {
            String birthday = DateUtil.formatDayToStr(v.getBirthday());
            try {
                Integer monthInterval = DateUtil.betweenMonths(DateUtil.millisToDateTime(today.getTime(), "yyyy-MM-dd"), birthday);//月龄
                v.setMonth(monthInterval);
            } catch (ParseException e) {
                throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
            }
        });

        List<ChildrenCheckRecordVo> voList = doList.stream().map(o -> ChildrenCheckRecordVo.of(o)).collect(Collectors.toList());

        return voList;
    }

    @Override
    public ChildrenMonthCheckRecordVo findByClassesByChildrenIdAndMonth(String childrenId, String month) {
        Date today = new Date();
        Integer monthInterval = 0;
        ChildrenMonthCheckRecordVo ChildrenMonthCheckRecordVo = new ChildrenMonthCheckRecordVo();
        //Classes classes =  classesRepository.getOne(classesId);
        List<CheckRecordDO> doList = childrenCheckRecordRepository.findCheckRecordByChildrenIdAndMonth(childrenId, month);
        if (doList.size() <= 0) {
            //throw new BusinessException(CHECK_IN_RECORD_NON, "宝宝没有签到记录");
            return null;
        }
        String birthday = DateUtil.formatDayToStr(doList.get(0).getBirthday());
        try {
            //月龄
            monthInterval = DateUtil.betweenMonths(DateUtil.millisToDateTime(today.getTime(), "yyyy-MM-dd"), birthday);//月龄
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }
        //班级名称
        String classesName = doList.get(0).getClassesName();
        //宝宝姓名
        String childrenName = doList.get(0).getChildrenName();
        List<CheckRecordVo> voList = doList.stream().map(o -> CheckRecordVo.of(o)).collect(Collectors.toList());
        ChildrenMonthCheckRecordVo vo = ChildrenMonthCheckRecordVo.of(classesName, childrenName, monthInterval.toString(), voList);
        return vo;

    }

    @Transactional
    @Override
    public boolean mulitCheckIn(StaffDTO staff, AreaDTO area, String[] childrenIds, Integer checkType) {
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");

        String content = "";
        List<CheckRecord> checkRecords = new ArrayList<CheckRecord>();
        for (String childrenId : childrenIds) {
            CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);

            Children children = childrenRepository.getOne(childrenId);
            ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
            if (Objects.isNull(extendInfo)) {
                extendInfo = new ChildrenExtendInfo();
            } else {
                if (null != extendInfo.getCheckTime()) {
                    String chekcDate = DateUtil.formatDayToStr(extendInfo.getCheckTime());
                    if (chekcDate.equals(currentDay) && extendInfo.getCheckStatus() == checkType)
                        throw new BusinessException(CHECK_STATUS_ERROR, "请勿重复签到");
                }

            }
            Integer checkStatus = ChildrenConstant.CheckStatus.JOIN.get(checkType).codeOf();

            extendInfo.setChildrenName(children.getName());
            extendInfo.setCheckStatus(checkStatus);
            extendInfo.setChildrenId(childrenId);
            extendInfo.setCheckTime(new Date());
            extendInfo.setHealthyStatus(0);
            extendInfo.setSickName("");
            extendInfo.setRemark("");
            childrenExtendInfoRepository.save(extendInfo);
            String image = "";
            if (Objects.isNull(record)) {
                record = new CheckRecord();
                RelClassesChildren firstByChildrenId = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
                if (!Objects.isNull(firstByChildrenId)){
                    record.setClassesId(firstByChildrenId.getClassesId());
                }
                record.setCheckInTime(now);
                record.setSpecialRecord("");
                record.setExceptionName("");
                record.setSickName("");
                record.setHealthyStatus(0);
                record.setHeight(null);
                record.setWeight(null);
                record.setHeader(null);
                record.setCheckType(CommonConstant.Platform.PAD.codeOf());
                record.setCheckInStaffId(staff.getId());
                record.setStatus(checkStatus);
                record.setChildrenId(childrenId);
                record.setCreated(now);
                checkRecordRepository.save(record);
                checkRecords.add(record);
            }


            if (ChildrenConstant.CheckStatus.JOIN.codeOf() == checkType) {
                feedsService.save(staff.getId(), childrenId, area.getId(), FeedsConstant.CHECK_IN, FeedsConstant.HEALTH_CHECK, String.format("%s在%s签到", children.getName(), area.getName()), content, image, "", record.getId());
            } else if (ChildrenConstant.CheckStatus.LEAVE.codeOf() == checkType) {
                feedsService.save(staff.getId(), childrenId, area.getId(), FeedsConstant.LEAVE, FeedsConstant.HEALTH_CHECK, String.format("%s在%s请假", children.getName(), area.getName()), content, image, "", record.getId());
            }

        }
        for (int i = 0; i < checkRecords.size(); i++) {
            wxPushService.pushCheckInRecord(checkRecords.get(i), null);
        }
        return true;
    }

    @Transactional
    @Override
    public boolean mulitCheckOut(StaffDTO staff, AreaDTO area, String[] childrenIds) {

        String staffId = staff.getId();
        String areaId = area.getId();

        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");

        String content = "";
        List<CheckRecord> checkRecords = new ArrayList<CheckRecord>();
        for (String childrenId : childrenIds) {
            CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenIdAndCheckOutTimeIsNull(begin, end, childrenId);
            if (Objects.isNull(record))
                throw new BusinessException(CHECK_IN_RECORD_NON, "没有签到记录");


            ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);

            if (!extendInfo.getCheckStatus().equals(ChildrenConstant.CheckStatus.JOIN.codeOf()))
                throw new BusinessException(CHECK_STATUS_ERROR, "签到状态有误,无签到记录");

            extendInfo.setCheckStatus(ChildrenConstant.CheckStatus.LEFT.codeOf());

            extendInfo.setChildrenId(childrenId);
            extendInfo.setCheckTime(new Date());
            childrenExtendInfoRepository.save(extendInfo);
            String image = "";


            record.setCheckOutTime(now);
            record.setCheckOutStaffId(staffId);
            Long duration = DateUtil.betweetMillis(record.getCheckInTime(), now);
            record.setStatus(ChildrenConstant.CheckStatus.LEFT.codeOf());
            record.setDuration(BigInteger.valueOf(duration < 0L ? 0L : duration));
            checkRecordRepository.save(record);

            //Time Line ====begin
            Children children = childrenRepository.getOne(childrenId);
            //AreaDTO area = ssoCallService.getAreaById(areaId);
            feedsService.save(staffId, childrenId, areaId, FeedsConstant.CHECK_OUT, FeedsConstant.HEALTH_CHECK, String.format("%s在%s离园", children.getName(), area.getName()), "", image, "", record.getId());
            //Time Line ====end

        }
        for (int i = 0; i < childrenIds.length; i++) {
            wxPushService.pushCheckOutRecord(childrenIds[i], null);
        }
        return true;
    }

//    @Override
//    public boolean deleteChildrenForStaff(String childrenId, String areaId){
//
//        Children children = childrenRepository.getByIdAndAreaId(childrenId, areaId);
//
//        childrenRepository.save(children);
//        return true;
//    }


    @Override
    public List<Children> birthdays(String areaId, String classesId) {
        //月份
        String startDate = DateUtil.getBeginOfCurrentMonth(new SimpleDateFormat("MM"));
        List<Children> list = childrenRepository.findByAreaIdAndBirthday(areaId, startDate, classesId);
        return list;
    }

    @Override
    public List<Children> getCheckStatus(String areaId, String checkStatus, String date, String classesId) {
        List<Children> list = childrenRepository.findByAreaIdAndCheckStatusAndCheckTime(areaId, checkStatus, date, classesId);
        return list;
    }

    @Override
    public List<BabyNClassInfoVO> getChildrenClassInfoForCrm(String areaId, Integer category, String childName, String classId, List<String> crmIds) {
        return classNativeRepository.findByAreaIdAndCategoryAndChildrenIds(areaId, category, childName, classId, crmIds);
    }

    @Override
    public List<BabyNClassInfoVO> getChildrenClassInfoForCrmV2(String areaId, String childName, String classId, List<String> crmIds) {
        return classNativeRepository.findByAreaIdAndCategoryAndChildrenIdsV2(areaId, childName, classId, crmIds);
    }

    @Override
    public List<BabyNClassInfoVO> getChildrenClassInfoForCrm(String areaId, String childName, String classId) {
        return classNativeRepository.findByAreaIdAndCategoryAndChildrenIds(areaId, childName, classId);
    }

    @Override
    public Integer clienteleAttendanceCount(String areaId, String clienteleId, String startTime, String endTime) {

        if (Objects.isNull(childrenRepository.findByCrmClienteleId(clienteleId))) {
            throw new BusinessException(IS_TARGET, "客户不存在");
        }
        if (Objects.isNull(startTime) || Objects.isNull(endTime) || Objects.isNull(clienteleId) || Objects.isNull(areaId)) {
            throw new BusinessException(IS_TARGET, "参数错误");
        }
        startTime = startTime + " 00:00:00";
        endTime = endTime + " 23:59:59";

        String sql = "SELECT  COUNT(a.id)  FROM  ( " +
                "SELECT cr.id FROM `check_record` cr INNER JOIN children c on cr.childrenId = c.id  " +
                "WHERE cr.status =1   " +
                "   AND  c.aid = '" + areaId + "'" +
                "   AND  c.crmClienteleId = '" + clienteleId + "'" +
                "   AND  DATE_FORMAT(cr.checkInTime,'%Y-%m-%d %H:%i:%S') >= DATE_FORMAT('" + startTime + "','%Y-%m-%d %H:%i:%S') " +
                "   AND  DATE_FORMAT(cr.checkInTime,'%Y-%m-%d %H:%i:%S') <= DATE_FORMAT('" + endTime + "','%Y-%m-%d %H:%i:%S')" +
                "  GROUP BY DATE_FORMAT(cr.checkInTime,'%Y-%m-%d') ) a  ";
        List<Object[]> objects = baseNativeSqlRepository.sqlArrayList(sql);
        int count = Integer.parseInt(String.valueOf(objects.get(0)));
        return count;
    }


    @Override
    public Map clienteleCourseTimeCount(String areaId, String clienteleId) {

        if (Objects.isNull(clienteleId) || Objects.isNull(areaId)) {
            throw new BusinessException(IS_TARGET, "参数错误");
        }
        if (Objects.isNull(childrenRepository.findByCrmClienteleId(clienteleId))) {
            throw new BusinessException(IS_TARGET, "客户不存在");
        }
        String sql = "SELECT cei.earlyLeftCourseNum,cei.earlyTotalCourseNum  FROM `children_extend_info` cei INNER JOIN children c on cei.childrenId = c.id  " +
                "WHERE   c.aid = '" + areaId + "'" +
                "   AND  c.crmClienteleId = '" + clienteleId + "'";
        List<Object[]> objects = baseNativeSqlRepository.sqlArrayList(sql);
        Map map = new HashMap();
        map.put("earlyLeftCourseNum", Integer.valueOf(objects.get(0)[0].toString()));
        map.put("earlyTotalCourseNum", Integer.valueOf(objects.get(0)[1].toString()));
        return map;
    }

    @Override
    public List<ChildrenContractInfoRecord> getChildrenContractInfoRecord( StaffDTO staffDTO, String childrenId, Date begin, Integer day, Integer type) {
        Children children = childrenRepository.getOne(childrenId);
        Map p = new HashMap();
        p.put("clienteleId", children.getCrmClienteleId());
        p.put("date", DateUtil.convertStr(begin));
        p.put("day", day);
        //1请假
        p.put("type", type);

        p.put("areaId", staffDTO.getAreaId());
        p.put("id", staffDTO.getId());
        p.put("realName", staffDTO.getRealName());
        //添加合同记录
        List<ChildrenContractInfoRecordVo> listVo = RemoteCallUtil.callOfList(crmServerURL + "/api/other_system/update_contract", p, null, ChildrenContractInfoRecordVo.class, "修改合同失败");
        List<ChildrenContractInfoRecord> ret = new ArrayList<>();
        if (listVo.size() > 0) {
            ret = listVo.stream().map(o -> {
                ChildrenContractInfoRecord po = new ChildrenContractInfoRecord();

                po.setClienteleId(o.getClienteleId());
                po.setContractId(o.getContractId());
                po.setType(o.getType());
                po.setEffectDay(o.getEffectDay());
                po.setSurplusOriginalLeaveDay(o.getSurplusOriginalLeaveDay());
                po.setSurplusLeaveDay(o.getSurplusLeaveDay());

                po.setNurseryEndDate(DateUtil.parseToDate(o.getNurseryEndDate()));
                po.setNurseryOriginalEndDate(DateUtil.parseToDate(o.getNurseryOriginalEndDate()));
                po.setCreatedBy(o.getCreatedBy());
                po.setCreatedName(o.getCreatedName());
                po.setRemark(o.getRemark());
                return po;
            }).collect(Collectors.toList());
            //保存修改合同记录
            childrenContractInfoRecordRepository.saveAll(ret);
        }
        return ret;
    }


    @Override
    @Transactional
    public String importChildrenList(String ticket, StaffDTO staff, List<ChildrenImportPO> list) throws Exception {
        if (Objects.isNull(list) || list.size() == 0) {
            throw new Exception("导入用户数据不能为空！");
        }
        List<ChildrenImportPO> childrenImportPOList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            childrenImportPOList(childrenImportPOList, list.get(i));
        }

        for (ChildrenImportPO childrenImport : childrenImportPOList) {

            List<AreaDTO>  areaDTOList = ssoCallService.getAreaName(childrenImport.getAreaName());
            if (areaDTOList.size()==0 || areaDTOList.size()>1){
                throw new Exception(childrenImport.getAreaName()+"园区名称不存在或重复，请联系管理员！");
            }
            Classes classes = classesRepository.findByNameAndAreaId(childrenImport.getClassName(),areaDTOList.get(0).getId());
            if (Objects.isNull(classes)){
                classes = new Classes();
                classes.setName(childrenImport.getClassName());
                classes.setAreaId(areaDTOList.get(0).getId());
                classes.setBaseTime(new Date());
                classes.setCategory(1);
                classes.setBeginMonth(1);
                classes.setEndMonth(12);
                classes =  classesRepository.save(classes);
            }
            ChildrenPO children = new ChildrenPO();
            children.setName(childrenImport.getChildrenName());
            children.setNickName(childrenImport.getChildrenName());
            if (Objects.isNull(childrenImport.getBirthday())) {
                children.setBirthday(new Date());
            } else {
                children.setBirthday(childrenImport.getBirthday());
            }
            if (Objects.isNull(childrenImport.getSex())) {
                children.setGender(0);
            } else if (StringUtils.equals("男", childrenImport.getSex())) {
                children.setGender(1);
            } else {
                children.setGender(0);
            }

            children.setLinkMans(childrenImport.getLinkMans());

            Children c = addWithRealtion(ticket, staff, children,areaDTOList.get(0).getId());

            RelClassesChildren relClassesChildren = new RelClassesChildren();
            relClassesChildren.setChildrenId(c.getId());
            relClassesChildren.setClassesId(classes.getId());
            relClassesChildrenRepository.save(relClassesChildren);
        }
        return "导入成功";
    }

    List<ChildrenImportPO> childrenImportPOList(List<ChildrenImportPO> childrenImportPOList, ChildrenImportPO childrenImportPO) {

        for (int i = 0; i < childrenImportPOList.size(); i++) {
            if (StringUtils.equals(childrenImportPOList.get(i).getChildrenName(), childrenImportPO.getChildrenName())) {
                ParentUserPO parentUserPO = new ParentUserPO();
                parentUserPO.setName(childrenImportPO.getUserName());
                parentUserPO.setRelation(childrenImportPO.getRelation());
                parentUserPO.setPhone(childrenImportPO.getPhone());

                if (Objects.isNull(childrenImportPOList.get(i).getLinkMans())) {
                    List<ParentUserPO> linkMans = new ArrayList<>();
                    linkMans.add(parentUserPO);
                    childrenImportPOList.get(i).setLinkMans(linkMans);
                } else {
                    childrenImportPOList.get(i).getLinkMans().add(parentUserPO);
                }
                return childrenImportPOList;
            }
        }

        ParentUserPO parentUserPO = new ParentUserPO();
        parentUserPO.setName(childrenImportPO.getUserName());
        parentUserPO.setRelation(childrenImportPO.getRelation());
        parentUserPO.setPhone(childrenImportPO.getPhone());
        if (Objects.isNull(childrenImportPO.getLinkMans())) {
            List<ParentUserPO> linkMans = new ArrayList<>();
            linkMans.add(parentUserPO);
            childrenImportPO.setLinkMans(linkMans);
        } else {
            childrenImportPO.getLinkMans().add(parentUserPO);
        }
        childrenImportPOList.add(childrenImportPO);
        return childrenImportPOList;

    }

    @Override
    @Transactional
    public void mulitCheckInV2(String ticket, AreaDTO area, StaffDTO staff, Integer checkType, String[] childrenIds) {
        for (int i = 0; i < childrenIds.length; i++) {
            checkIn(area, staff, 1, childrenIds[i], null, null, null,
                    null, null, null, null, null, null, null, null,ticket);
        }
    }

    @Override
    public void updateById(Children byId) {
        childrenRepository.save(byId);
    }

    @Override
    @Transactional
    public Children addByLeads(String ticket, StaffDTO staff, ChildrenPO children) {
        ParentUserPO parent = children.getLinkMans().get(0);
        System.out.println("children.getIdCard()======================="+children.getIdCard());
        System.out.println("children======================="+children);
        //创建教务i系统宝宝
        Children c = Children.of_crm(children.getName(),
                Objects.isNull(children.getNickName()) ? "" : children.getNickName(),
                children.getGender(),
                children.getBirthday(),
                staff.getAreaId(),
                Objects.isNull(children.getAddress()) ? "" : children.getAddress(),
                children.getCrmClienteleId(),
                staff.getId(),
                children.getChildAge(),
                children.getIdCard(),
                children.getImgUrl());

//        c.setStaffId(children.getStaffId());
//        c.setIdCard(children.getIdCard());
//        c.setImgUrl(children.getImgUrl());
        //最后如果有生效时间，则开始激活宝宝
        Date nursyValidDate = children.getNursyValidTo();
        if (nursyValidDate != null && nursyValidDate.compareTo(new Date()) > 0) {
            //指定日期有效
            c.setCourseStartDate(new Date());
            c.setStatus(ChildrenConstant.ChildrenStatus.ACTIVE.codeOf());
        }
        c = add1(c, parent.getPhone(), parent.getName(), parent.getCompany(), parent.getRelation(),parent.getProvince(),parent.getCity(),parent.getDistrict(),parent.getDetailedAddress(),parent.getEducation(),parent.getPosition(),parent.getEmail(),parent.getBirthDay());

        //处理更多的家长
        for (int i = 1; i < children.getLinkMans().size(); i++) {
            ParentUserPO po = children.getLinkMans().get(i);

            ParentUser parentUser = appUserRepository.findByPhone(po.getPhone());
            if (Objects.isNull(parentUser)) {
                parentUser = ParentUser.of(po.getName(), po.getPhone(), po.getCompany(),po.getProvince(),po.getCity(),po.getDistrict(),po.getDetailedAddress(),po.getEducation(),po.getPosition(),po.getPosition());
                //创建相应联系人
                parentUser.setEmail(po.getEmail());
                parentUser.setBirthDay(parent.getBirthDay());
                parentUser = appUserRepository.save(parentUser);
            }

            relUserChildrenRepository.save(RelUserChildren.of(parentUser.getId(), c.getId(), po.getRelation(), po.getRemark()));
        }

        if (nursyValidDate != null && nursyValidDate.compareTo(new Date()) > 0 && children.getCameraValidTo() != null && !StringUtils.equals(children.getCameraValidTo(), "")) {
            //处理托班激活信息
            ChildrenExtendInfo extendInfo = extendInfoRepository.findByChildrenId(c.getId());
            //托班相关信息
            extendInfo.setNurseryEndDate(nursyValidDate);
            extendInfo.setNurseryStatus(ChildrenConstant.NurseryStatus.HAS_COURSE.codeOf());
            extendInfo.setCameraValidTo(DateUtil.parseToDateMilis(children.getCameraValidTo() + " 23/59/59"));
            extendInfoRepository.save(extendInfo);
        }

        return c;
    }

    @Override
    public void renewPush(StaffDTO staff, AreaDTO area, String[] childrenIds) {
        for (String childrenId:childrenIds){
            Children children = childrenRepository.getOne(childrenId);
            children.setPushStatus(1);
            childrenRepository.save(children);

            wxPushService.renewPush(childrenId, children);
        }

    }
}
